package dao;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;

import util.DataAcessLayerException;
import util.HibernateFactory;

public abstract class AbstractDao<T> {

	/**
	 * 
	 */
	protected Session session;
	/**
	 * 
	 */
	protected Transaction tx;

	/**
	 * 
	 */
	public AbstractDao() {
		HibernateFactory.buildIfNeeded();
	}

	/**
	 * @return
	 */
	protected Session getSession() {
		return session;
	}

	/**
	 * @return
	 */
	protected Transaction getTx() {
		return tx;
	}

	/**
	 * @param obj
	 */
	protected void saveOrUpdate(T obj) {
		try {
			startOperation();
			session.saveOrUpdate(obj);
			tx.commit();
		} catch (HibernateException e) {
			handleException(e);
		} finally {
			HibernateFactory.close(session);
		}
	}

	/**
	 * @param obj
	 */
	protected void delete(T obj) {
		try {
			startOperation();
			session.delete(obj);
			tx.commit();
		} catch (HibernateException e) {
			handleException(e);
		} finally {
			HibernateFactory.close(session);
		}
	}

	/**
	 * @param clazz
	 * @param id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected T find(Class<T> clazz, Long id) {
		T obj = null;
		try {
			startOperation();
			obj = (T) session.get(clazz, id);
			tx.commit();
		} catch (HibernateException e) {
			handleException(e);
		} finally {
			HibernateFactory.close(session);
		}
		return obj;
	}

	/**
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected List<T> findAll(Class<T> clazz) {
		List<T> objects = null;
		try {
			startOperation();
			objects = session.createQuery("from " + clazz.getName()).list();
			tx.commit();
		} catch (HibernateException e) {
			handleException(e);
		} finally {
			HibernateFactory.close(session);
		}
		return objects;
	}

	/**
	 * @param query
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected List createSQL(String query) {
		List<T> objects = null;
		try {
			startOperation();
			objects = session.createQuery(query).list();
			tx.commit();
		} catch (HibernateException e) {
			handleException(e);
		} finally {
			HibernateFactory.close(session);
		}
		return objects;
	}

	/**
	 * @param e
	 * @throws DataAcessLayerException
	 */
	protected void handleException(HibernateException e)
			throws DataAcessLayerException {
		HibernateFactory.rollback(tx);
		throw new DataAcessLayerException(e);
	}

	/**
	 * @throws HibernateException
	 */
	protected void startOperation() throws HibernateException {
		session = HibernateFactory.openSession();
		tx = session.beginTransaction();
	}
}
